from rest_framework_jwt.utils import jwt_decode_handler
from django.contrib.auth.models import AnonymousUser
from channels.db import database_sync_to_async
from user.models import UserProfile
class JWTAuthMiddleware:
    def __init__(self, app):
        self.app = app
    # 在Django Channels中，中间件类通过实现__call__方法来处理传入的连接。
    # 当有新的连接到来时，这个方法会被调用，处理scope、receive和send参数。
    # scope包含连接的相关信息，比如请求的路径、查询参数等；
    # receive和send用于处理消息的接收和发送
    async def __call__(self, scope, receive, send):
        query_string = scope.get("query_string", b"").decode()
        token = None

        # 解析查询参数中的token
        print('中间件query',query_string)
        for param in query_string.split('&'):
            if param.startswith('token='):
                print('拿到了token')
                token = param.split('=')[1]
                print('token',token)
                break
        if token:
            try:
                # 使用rest_framework_jwt的解码方法
                payload = jwt_decode_handler(token)
                print('payload',payload)
                # 从payload中获取用户ID并设置到scope中
                user = await self.get_user(payload['user_id']) # type: ignore
                scope['user'] = user
            except Exception as e:
                print('token错误',e)
                # 如果token无效或过期，设置为匿名用户
                scope['user'] = AnonymousUser()
        else:
            # 设置为匿名用户
            scope['user'] = AnonymousUser()
        # DjangoChannels的中间件是通过包装应用（app）来实现的。
        # 每个中间件都会接收一个app，并在处理完自己的逻辑后，
        # 将控制权传递给下一个中间件或最终的消费者
        # scope包含链接的相关信息，例如路径，查询参数等，receive和send用于处理消息的接收和发送。
        return await self.app(scope, receive, send)

    # 这是一个同步的ORM操作。在异步环境中直接调用会阻塞事件循环，
    # 所以必须用database_sync_to_async来包装，使其变成异步函数。
    @database_sync_to_async
    def get_user(self, user_id):
        return UserProfile.objects.get(id=user_id)